<?php

class Router {
	var $uri;
	var $uri_string;
	var $segments;
	
	var $cls;
	var $fun;
	var $param;
	
	function __construct()
	{
		if ('cli'==php_sapi_name()) {
			global $argv;
			$new_argv = $argv;
			array_shift($new_argv);
			$this->segments = $new_argv;
		}else{
			$this->_fetch_uri_string();
			$this->_explode_segments();
		}
	}

	function routing()
	{
		global $CFG;
		//@滚蛋不好听... fuck off 吧...//不存在前缀直接滚蛋... 
		if (!isset($CFG['router_class_prefix'])) {
			return false;
		}
		if ((!is_array($this->segments) || count($this->segments)<2 ) && ('cli'!=php_sapi_name())) {
			$this->param = $CFG['router_default_param'];
			$this->cls = $CFG['router_default_class']; 
			$this->fun = $CFG['router_default_function'];
		}else{
			$this->_find_seg();
		}
		if (is_array($this->param)) {
			$this->param = array_values($this->param);
		}
		if (!is_array($this->param) || !count($this->param)) {
			$this->param = array();
                }
                if ($this->fun!=$CFG['router_default_function'] && strncmp($this->fun, '_', 1)===0){ //过滤掉以下划线开头的方法，为内部方法
                        array_unshift($this->param, $this->fun) ;
                        $this->fun = $CFG['router_default_function'] ;
                }
		$this->cls = $CFG['router_class_prefix'].$this->cls;
		$method = new ReflectionMethod($this->cls, $this->fun);		
		$method->invokeArgs(new $this->cls,$this->param);
	}
    /**
     * 拆分成类 方法 参数
     * 
     * @author virowin<virowin@gmail.com>
     * @version 1.0 2012-03-19 17:19
     * */
	function _find_seg(){
		global $CFG;
	    $this->param = $this->segments;
	    //默认路径
	    $file_src = $CFG['class_path']."/".$CFG ['router_class_position'];
	    $this->cls = array();
//	    if($_GET['router_debug']){
//	        var_dump(file_exists($file_src."/Ajax/AjaxGetUserInfo.php"));
//	    }
	    //查找控制器 直到文件存在
	    while (!file_exists($file_src."/".str_replace('_','/',implode('/',$this->cls)).".php")) {
	        if(count($this->param) <1){
	            return error(100061,"无有效的控制器");
	        }
	       $this->cls[] = ucfirst(array_shift($this->param));
	    }
	    $this->cls = implode("_",$this->cls);
	    if(count($this->param) >=1)
	       $this->fun = array_shift($this->param);
	    else 
	       $this->fun = $CFG ['router_default_function'];
	    
	}
	
	
	/**
	 * below is the url funciton
	 *
	 */
	function _fetch_uri_string()
	{
		if ($uri = $this->_detect_uri())
		{
			$this->_set_uri_string($uri);
			return;
		}
	}
	function _set_uri_string($str)
	{
		// Filter out control characters
		$str = remove_invisible_characters($str, FALSE);
		
		// If the URI contains only a slash we'll kill it
		$this->uri_string = ($str == '/') ? '' : $str;
	}
	private function _detect_uri()
	{
		if ( ! isset($_SERVER['QUERY_STRING']))
		{
			return '';
		}

		$uri = $_SERVER['QUERY_STRING'];
		if (strpos($uri, $_SERVER['SCRIPT_NAME']) === 0)
		{
			$uri = substr($uri, strlen($_SERVER['SCRIPT_NAME']));
		}
		elseif (strpos($uri, dirname($_SERVER['SCRIPT_NAME'])) === 0)
		{
			$uri = substr($uri, strlen(dirname($_SERVER['SCRIPT_NAME'])));
		}

		// This section ensures that even on servers that require the URI to be in the query string (Nginx) a correct
		// URI is found, and also fixes the QUERY_STRING server var and $_GET array.
		if (strncmp($uri, '?/', 2) === 0)
		{
			$uri = substr($uri, 2);
		}
		$parts = preg_split('#\&#i', $uri, 2);
		$uri = $parts[0];
		if (isset($parts[1]))
		{
			$_SERVER['QUERY_STRING'] = $parts[1];
			parse_str($_SERVER['QUERY_STRING'], $_GET);
		}
		else
		{
			$_SERVER['QUERY_STRING'] = '';
			$_GET = array();
		}
		
		if ($uri == '/' || empty($uri))
		{
			return '/';
		}
				
		$uri = parse_url($uri, PHP_URL_PATH);

		// Do some final cleaning of the URI and return it
		return str_replace(array('//', '../'), '/', trim($uri, '/'));
	}
	function _filter_uri($str)
	{
		// Convert programatic characters to entities
		$bad	= array('$',		'(',		')',		'%28',		'%29');
		$good	= array('&#36;',	'&#40;',	'&#41;',	'&#40;',	'&#41;');
		return str_replace($bad, $good, $str);
	}
	
	function _explode_segments()
	{
		foreach (explode("/", preg_replace("|/*(.+?)/*$|", "\\1", $this->uri_string)) as $val)
		{
			// Filter segments for security
			$val = trim($this->_filter_uri($val));

			if ($val != '')
			{
				$this->segments[] = $val;
			}
		}
	}

}
